ingress控制器作用
ingress controller可以为kubernetes 集群外用户访问Kubernetes集群内部pod提供代理服务。
- 提供全局访问代理
- 访问流程: 用户-->ingress controller-->service-->pod
nginx ingress controller部署
curl -k https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/baremetal/deploy.yaml -o deploy.yaml
kubectl apply -f deploy.yaml #默认是nodeport方式将ingress暴露在外
kubectl get pods -n ingress-nginx
ingress-http案例
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-nginx1 #自定义ingress名称
namespace: test
annotations:
ingressclass.kubernetes.io/is-default-class: "true"
kubernetes.io/ingress.class: nginx
spec:
rules:
- host: www.nginx1.com # 自定义域名
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: nginx-svc1
port:
number: 80
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-nginx #自定义ingress名称
namespace: test
annotations:
ingressclass.kubernetes.io/is-default-class: "true"
kubernetes.io/ingress.class: nginx
spec:
rules:
- host: www.nginx1.com # 自定义域名
http:
paths:
- pathType: Prefix
path: "/nginx1"
backend:
service:
name: nginx-svc1
port:
number: 80
- pathType: Prefix
path: "/nginx2"
backend:
service:
name: nginx-svc1
port:
number: 80
ingress-https案例
kubectl create secret tls nginx-tls-secret --cert=server.crt --key=server.key -n ingress-nginx
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-nginx #自定义ingress名称
namespace: test
annotations:
ingressclass.kubernetes.io/is-default-class: "true"
kubernetes.io/ingress.class: nginx
spec:
tls:
- hosts:
- www.nginx1.com # 域名
secretName: nginx-tls-secret
rules:
- host: www.nginx1.com # 自定义域名
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: nginx-svc1
port:
number: 80
Ingress透传真实IP
- 访问流程的架构图如下:
- 外部nginx需要配置:
proxy_set_header Host $host; #将客户端请求中的 Host 头(或当前访问的域名)原样转发给后端服务器。假设用户访问的是:http://www.testnginx.com,这个请求头中会带有:www.testnginx.com,我们ingress是通过域名转发的,所以这项必须配置,不然转发不到后端服务。
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; #X-Forwarded-For 是一个 HTTP 标准头,用于记录 请求经过的代理链路中的所有 IP 地址。用户 IP 是 203.0.113.10,Nginx 本身已有 X-Forwarded-For: 100.100.137.202,Nginx 添加后变成:X-Forwarded-For: 100.100.137.202, 203.0.113.10
- ingress需要配置:
kubectl edit cm ingress-nginx-controller -n ingress-nginx
data:
compute-full-forwarded-for: "true"
use-forwarded-headers: "true"
compute-full-forwarded-for: "true":
设置这个参数对应的nginx真实配置:proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
当 Ingress-NGINX 转发请求时,它会将自己的 IP 加入 X-Forwarded-For,构成完整链路。
$proxy_add_x_forwarded_for 表示:原有的 X-Forwarded-For 值 + 当前请求的客户端地址。
use-forwarded-headers: "true":
设置这个参数对应的nginx真实配置:
real_ip_header X-Forwarded-For;
set_real_ip_from 0.0.0.0/0;
real_ip_recursive on;
意思是:从 X-Forwarded-For 获取真实客户端 IP,且允许递归解析这个字段中的多个地址。这样Ingress-NGINX的remote_addr取X-Forwarded-For的第一个ip为真实ip地址。
- Nginx-pod上配置:
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 当 Ingress-NGINX 转发请求时,它会将自己的 IP 加入 X-Forwarded-For,构成完整链路。
set_real_ip_from 0.0.0.0/0; # 所信任的代理ip
real_ip_header X-Forwarded-For;
real_ip_recursive on;
业务pod通过X-Forwarded-For获取真实IP。
注意:网上有很多人都说需要配置ingress的svc(nodeport类型),这里做出解释:
ExternalTrafficPolicy=Local(针对 NodePort 或 LoadBalancer)和ExternalTrafficPolicy=Cluster 区别:
配置 | 是否保留客户端真实 IP | 流量是否可以转发到其它节点 | kube-proxy 行为 | 使用场景 |
---|---|---|---|---|
Cluster (默认) |
❌ 不保留(源 IP 被 NAT 成 Node IP) | ✅ 是,转发到任何节点的 Pod | 会将流量负载均衡到所有节点上的 Pod | 标准服务可用性、流量分散 |
Local |
✅ 保留客户端真实 IP | ❌ 否,只转发到本节点上的 Pod | 只会转发给本节点的 Pod,否则拒绝连接 | 想保留真实 IP、或结合负载均衡器使用 |
我这里ingress的svc(nodeport类型)设置的是ExternalTrafficPolicy=Cluster 还能获取到真实IP的原因是:
我的请求是经过“前置 Nginx ”转发过来的,externalTrafficPolicy: Local 是用于直接(重点:是直接访问)访问 NodePort 或 LoadBalancer 的情况
也就是说,客户端请求并不是直接打到 NodePort,而是先被一个 Nginx转发进来的,这些前置代理会添加或保留 X-Forwarded-For
头。
在外部 Nginx 加了:
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
在 Ingress-NGINX 的 ConfigMap 设置了:
use-forwarded-headers: "true"
compute-full-forwarded-for: "true"
所以,虽然 Ingress Pod 看到的 remote_addr 是 kube-proxy 的节点 IP,但它通过 X-Forwarded-For 能取到真实客户端 IP